//@author A0101712B
#include <Windows.h>
#include "UI.h"


using namespace Twentyfifth;
using namespace std;

WORD GetConsoleTextAttribute(HANDLE hCon) {
	CONSOLE_SCREEN_BUFFER_INFO con_info;
	GetConsoleScreenBufferInfo(hCon, &con_info);
	return con_info.wAttributes;
}

void TwentyfifthUI::printWelcomeMessage() {

	HWND console = GetConsoleWindow();
	RECT r;
	GetWindowRect(console, &r); //stores the console's current dimensions

	MoveWindow(console, r.left, r.top, UI_DEFAULT_WIDTH, UI_DEFAULT_HEIGHT, TRUE);

	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	const int saved_colors = GetConsoleTextAttribute(hConsole);

	SetConsoleTextAttribute(hConsole, COLOR_YELLOW);

	cout << UI_WELCOME_MESSAGE << endl;

	SetConsoleTextAttribute(hConsole, saved_colors);

	return;
}

void TwentyfifthUI::printUserPrompt() {
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	const int saved_colors = GetConsoleTextAttribute(hConsole);

	SetConsoleTextAttribute(hConsole, COLOR_WHITE);

	cout << UI_PROMPT_USER;

	SetConsoleTextAttribute(hConsole, saved_colors);
	return;
}

void TwentyfifthUI::printLongMessage(string message) {
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	const int saved_colors = GetConsoleTextAttribute(hConsole);

	istringstream istream(message);
	string word;
	getline(istream, word);

	SetConsoleTextAttribute(hConsole, COLOR_DARK_YELLOW);

	cout << endl;
	cout << word << endl;

	SetConsoleTextAttribute(hConsole, COLOR_YELLOW);

	while (getline(istream, word)) {
		cout << setw(DEFAULT_ID_WIDTH) << UI_SINGLE_SPACE;
		cout << word << endl;
	}
	cout << endl;

	SetConsoleTextAttribute(hConsole, saved_colors);
}

void TwentyfifthUI::printMessage(string message) {
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	const int saved_colors = GetConsoleTextAttribute(hConsole);

	//checking whether string is long
	int counter = ZERO;
	for (int i = ZERO; i<(int)message.length(); i++) {
		if (message[i] == CHAR_ENDLINE) {
			counter++;
		}
	}
	//if yes, switch to printLongMessage function
	if (counter>SHORTSTRING_BOUNDARY) {
		printLongMessage(message);
		return;
	}
	//if not, continue with printing the message

	SetConsoleTextAttribute(hConsole, COLOR_YELLOW);

	cout << endl;
	cout << message << endl;

	SetConsoleTextAttribute(hConsole, saved_colors);
	return;
}

void TwentyfifthUI::printVectorMessage(vector<Task> taskVector) {

	if (taskVector.empty()) {
		return;
	}

	vector<Task> timedTasks = getTimedTasks(taskVector);
	vector<Task> deadlineTasks = getDeadlineTasks(taskVector);
	vector<Task> normalTasks = getNormalTasks(taskVector);

	system(UI_CLEAR.c_str());

	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	const int saved_colors = GetConsoleTextAttribute(hConsole);

	SetConsoleTextAttribute(hConsole, COLOR_RED_ON_BLUE);

	cout << UI_TABLE_LINE << endl;
	cout << setw(DEFAULT_TABLE_WIDTH) << UI_SINGLE_SPACE << endl;

	// start timed task.
	SetConsoleTextAttribute(hConsole, COLOR_YELLOW_ON_BLUE);

	if (timedTasks.empty()) {
		printCenteredMessage(UI_MSG_ERR_NO_TIMED_TASK);
	} else {
		cout << UI_SINGLE_SPACE;
		cout << setiosflags(ios::left) << setw(DEFAULT_ID_WIDTH) << UI_ID;
		cout << setiosflags(ios::left) << setw(DEFAULT_TIME_WIDTH) << UI_TIME;
		cout << setiosflags(ios::left) << setw(DEFAULT_DESC_WIDTH) << UI_DESCRIPTION << endl;

		SetConsoleTextAttribute(hConsole, COLOR_WHITE_ON_BLUE);

		for (size_t i = 0; i < timedTasks.size(); i++) {
			cout << UI_SINGLE_SPACE;
			cout << setiosflags(ios::left) << setw(DEFAULT_ID_WIDTH) << timedTasks[i].getId();
			string tempTime = timedTasks[i].getStart().toString() + UI_TIME_SEPARATOR + timedTasks[i].getEnd().toString();
			cout << setiosflags(ios::left) << setw(DEFAULT_TIME_WIDTH) << tempTime;
			string tempDescription = timedTasks[i].getDescription();
			if (tempDescription.length() >= DEFAULT_DESC_WIDTH_DEADLINE) {
				tempDescription = tempDescription.substr(ZERO, SHRUNK_DESC_WIDTH);
				tempDescription += UI_TOBE_CONTINUED;
			}
			cout << setiosflags(ios::left) << setw(DEFAULT_DESC_WIDTH) << tempDescription << endl;
		}
	}

	nextLine();
	// end timed tasks.
	SetConsoleTextAttribute(hConsole, COLOR_RED_ON_BLUE);
	cout << UI_TABLE_SEPARATOR << endl;
	cout << setw(DEFAULT_TABLE_WIDTH) << UI_SINGLE_SPACE << endl;
	// start deadline tasks.
	SetConsoleTextAttribute(hConsole, COLOR_YELLOW_ON_BLUE);
	if (deadlineTasks.empty()) {
		printCenteredMessage(UI_MSG_ERR_NO_DEADLINE_TASK);
	} else {
		cout << UI_SINGLE_SPACE;
		cout << setiosflags(ios::left) << setw(DEFAULT_ID_WIDTH) << UI_ID;
		cout << setiosflags(ios::left) << setw(DEFAULT_TIME_WIDTH_DEADLINE) << UI_DEADLINE;
		cout << setiosflags(ios::left) << setw(DEFAULT_DESC_WIDTH_DEADLINE) << UI_DESCRIPTION << endl;

		SetConsoleTextAttribute(hConsole, COLOR_WHITE_ON_BLUE);

		for (size_t i = 0; i < deadlineTasks.size(); i++) {
			cout << UI_SINGLE_SPACE;
			cout << setiosflags(ios::left) << setw(DEFAULT_ID_WIDTH) << deadlineTasks[i].getId();
			string tempTime = UI_DEADLINE_PREFIX + deadlineTasks[i].getDeadline().toString();
			cout << setiosflags(ios::left) << setw(DEFAULT_TIME_WIDTH_DEADLINE) << tempTime;
			string tempDescription = deadlineTasks[i].getDescription();
			if (tempDescription.length() >= DEFAULT_DESC_WIDTH_DEADLINE) {
				tempDescription = tempDescription.substr(ZERO, SHRUNK_DESC_WIDTH_DEADLINE);
				tempDescription += UI_TOBE_CONTINUED;
			}
			cout << setiosflags(ios::left) << setw(DEFAULT_DESC_WIDTH_DEADLINE) << tempDescription << endl;
		}
	}

	nextLine();
	// end deadline tasks.
	SetConsoleTextAttribute(hConsole, COLOR_RED_ON_BLUE);
	cout << UI_TABLE_SEPARATOR << endl;
	cout << setw(DEFAULT_TABLE_WIDTH) << UI_SINGLE_SPACE << endl;
	// start normal tasks.
	SetConsoleTextAttribute(hConsole, COLOR_YELLOW_ON_BLUE);

	if (normalTasks.empty()) {
		printCenteredMessage(UI_MSG_ERR_NO_NORMAL_TASK);
	} else {
		cout << UI_SINGLE_SPACE;
		cout << setiosflags(ios::left) << setw(DEFAULT_ID_WIDTH) << UI_ID;
		cout << setiosflags(ios::left) << setw(DEFAULT_TICK_WIDTH_NORMAL) << UI_SINGLE_SPACE;
		cout << setiosflags(ios::left) << setw(DEFAULT_DESC_WIDTH_NORMAL) << UI_DESCRIPTION << endl;

		SetConsoleTextAttribute(hConsole, COLOR_WHITE_ON_BLUE);
		for (size_t i = 0; i < normalTasks.size(); i++) {
			cout << UI_SINGLE_SPACE;
			cout << setiosflags(ios::left) << setw(DEFAULT_ID_WIDTH) << normalTasks[i].getId();
			if (normalTasks[i].isDone()) {
				cout << setiosflags(ios::left) << setw(DEFAULT_TICK_WIDTH_NORMAL) << UI_DONE;
			} else {
				cout << setiosflags(ios::left) << setw(DEFAULT_TICK_WIDTH_NORMAL) << UI_NOTDONE;
			}
			string tempDescription = normalTasks[i].getDescription();
			if (tempDescription.length() >= DEFAULT_DESC_WIDTH_NORMAL) {
				tempDescription = tempDescription.substr(ZERO, SHRUNK_DESC_WIDTH_NORMAL);
				tempDescription += UI_TOBE_CONTINUED;
			}
			cout << setiosflags(ios::left) << setw(DEFAULT_DESC_WIDTH_NORMAL) << tempDescription << endl;
		}
	}

	nextLine();
	// end normal tasks.

	SetConsoleTextAttribute(hConsole, COLOR_RED_ON_BLUE);

	cout << UI_TABLE_LINE << endl;

	SetConsoleTextAttribute(hConsole, COLOR_DARK_CYAN);

	cout << UI_NOTICE1 << endl;
	cout << UI_NOTICE2 << endl;

	SetConsoleTextAttribute(hConsole, saved_colors);
	return;
}

bool TwentyfifthUI::compareTimedTask(Task a, Task b) {
	if (a.getEnd() == b.getEnd()) {
		return a.getId() < b.getId();
	}
	return a.getEnd() < b.getEnd();
}

bool TwentyfifthUI::compareDeadlineTask(Task a, Task b) {
	if (a.getDeadline() == b.getDeadline()) {
		return a.getId() < b.getId();
	}
	return a.getDeadline() < b.getDeadline();
}

bool TwentyfifthUI::compareNormalTask(Task a, Task b) {
	return a.getId() < b.getId();
}

vector<Task> TwentyfifthUI::getTimedTasks(vector<Task> taskVector) {
	vector<Task> vt;
	for (size_t i = 0; i < taskVector.size(); i++) {
		if (taskVector[i].getTaskType() == Task::TIMED_TASK) {
			vt.push_back(taskVector[i]);
		}
	}
	sort(vt.begin(), vt.end(), &TwentyfifthUI::compareTimedTask);
	return vt;
}

vector<Task> TwentyfifthUI::getDeadlineTasks(vector<Task> taskVector) {
	vector<Task> vt;
	for (size_t i = 0; i < taskVector.size(); i++) {
		if (taskVector[i].getTaskType() == Task::DEADLINE_TASK) {
			vt.push_back(taskVector[i]);
		}
	}
	sort(vt.begin(), vt.end(), &TwentyfifthUI::compareDeadlineTask);
	return vt;
}

vector<Task> TwentyfifthUI::getNormalTasks(vector<Task> taskVector) {
	vector<Task> vt;
	for (size_t i = 0; i < taskVector.size(); i++) {
		if (taskVector[i].getTaskType() == Task::TASK) {
			vt.push_back(taskVector[i]);
		}
	}
	sort(vt.begin(), vt.end(), &TwentyfifthUI::compareNormalTask);
	return vt;
}


void TwentyfifthUI::nextLine() {
	cout << setw(79) << UI_SINGLE_SPACE << endl;
}

void TwentyfifthUI::printCenteredMessage(string message) {
	int tableWidth = DEFAULT_TABLE_WIDTH;
	int messageLength = message.length();
	int offsetFromLeft = (tableWidth - messageLength) / 2;
	int offsetFromRight = (tableWidth - offsetFromLeft - messageLength);
	cout << setiosflags(ios::left) << setw(offsetFromLeft) << UI_SINGLE_SPACE;
	cout << message;
	cout << setiosflags(ios::left) << setw(offsetFromRight) << UI_SINGLE_SPACE << endl;
}